package com.xianniu.ltc.job;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.rebuild.core.UserContextHolder;
import com.xianniu.ltc.aspect.RecordSaveAspect;
import com.xianniu.ltc.enums.ProjectReportEnum;
import com.xianniu.ltc.mapper.TProjectReportMapper;
import com.xianniu.ltc.mapper.TRbhetong0Mapper;
import com.xianniu.ltc.model.entity.TProjectReportDTO;
import com.xianniu.ltc.model.entity.TRbhetong0DTO;
import com.xianniu.ltc.model.po.AddProjectReportPO;
import com.xianniu.ltc.service.ExternalService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.sso.core.entity.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * 功能描述: 每天23：59定时汇总APP所需报表数据
 *
 * @Param:
 * @Return:
 * @Author: wrj
 * @Date: 2021/12/8 5:18 下午
 */
@Slf4j
@Component
public class ProjectReportJobHandler extends IJobHandler {

    @Autowired
    private ExternalService externalService;
    @Resource
    private TRbhetong0Mapper tRbhetong0Mapper;
    @Resource
    private TProjectReportMapper tProjectReportMapper;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    // 系统用户
    public final String SYSTEM_USER = "001-0000000000000000";

//    @XxlJob("projectReportJobHandler")
    @Override
    @Trace
    public void execute() throws Exception{
        try {
            projectReportJobHandler();
        } catch (Exception e) {
            XxlJobHelper.handleFail(e.getCause().getMessage());
            e.printStackTrace();
        }
        XxlJobHelper.handleSuccess();
    }

    public void projectReportJobHandler() throws Exception {
        // 先删除历史LTC数据
        log.info("--------------->先删除历史LTC数据开始");
        long startTime = System.currentTimeMillis();
        ReturnT returnT = externalService.delProjectReportDayData();
        log.info("--------------->先删除历史LTC数据开始：{}", JSON.toJSON(returnT));
        List<AddProjectReportPO> aReportPOList = tRbhetong0Mapper.rbHuiKuanDan();
        List<AddProjectReportPO> bReportPOList = tRbhetong0Mapper.rbHeTongProjectM();
        List<AddProjectReportPO> cReportPOList = tRbhetong0Mapper.rbFuKuanDan();
        List<AddProjectReportPO> dReportPOList = tRbhetong0Mapper.huiKuanJiHua();
        List<AddProjectReportPO> eReportPOList = tRbhetong0Mapper.xiangMuLeiFuKuanApproval();
        List<AddProjectReportPO> fgReportPOList = new ArrayList<>();
        List<AddProjectReportPO> fReportPOList = tRbhetong0Mapper.xiangMuLeiFuKuanTender();
        List<AddProjectReportPO> gReportPOList = tRbhetong0Mapper.xiangMuLeiBaoXiaoTender();
        fgReportPOList.addAll(fReportPOList);
        fgReportPOList.addAll(gReportPOList);
        List<AddProjectReportPO> oReportPOList = tRbhetong0Mapper.rbFenyongExtract();
        List<AddProjectReportPO> pqReportPOList = new ArrayList<>();
        List<AddProjectReportPO> pReportPOList = tRbhetong0Mapper.xiangMuLeiFuKuanNoTender();
        List<AddProjectReportPO> qReportPOList = tRbhetong0Mapper.xiangMuLeiBaoXiaoNoTender();
        pqReportPOList.addAll(pReportPOList);
        pqReportPOList.addAll(qReportPOList);
        // 1，插入项目回款报表数据
        CompletableFuture<Void> receiveFuture = CompletableFuture.runAsync(() -> {
            projectReceivable(aReportPOList);
        }, threadPoolTaskExecutor);

        // 2，插入交付成本统计报表数据
        CompletableFuture<Void> deliveryFuture = CompletableFuture.runAsync(() -> {
            projectDeliveryCost(cReportPOList);
        }, threadPoolTaskExecutor);
        // 3.插入回款金额概况报表数据
        CompletableFuture<Void> projectReceivableFuture = CompletableFuture.runAsync(() -> {
            projectReceivableMoney(aReportPOList, bReportPOList, dReportPOList);
        }, threadPoolTaskExecutor);
        // 4.支出金额报表数据
        CompletableFuture<Void> projectSpendingAmountFuture = CompletableFuture.runAsync(() -> {
            projectSpendingAmount(eReportPOList, cReportPOList);
        }, threadPoolTaskExecutor);
        // 5.支出费用明细
        CompletableFuture<Void> projectSpendingFuture = CompletableFuture.runAsync(() -> {
            projectSpendingDetail(cReportPOList, fgReportPOList, oReportPOList, pqReportPOList);
        }, threadPoolTaskExecutor);
        CompletableFuture.allOf(receiveFuture, deliveryFuture, projectReceivableFuture, projectSpendingAmountFuture, projectSpendingFuture).get();
        long endTime = System.currentTimeMillis();
        log.info("统计项目报表耗时:{}ms", (endTime - startTime));
    }

    /**
     * 插入项目回款报表数据
     */
    public void projectReceivable(List<AddProjectReportPO> aReportPOList) {
        if (CollectionUtils.isEmpty(aReportPOList)){
            return;
        }
        for (AddProjectReportPO reportPO : aReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                List<TRbhetong0DTO> bReportPOList = tRbhetong0Mapper.rbHeTong(reportPO.getProjectCode()); //查询合同
                if (!CollectionUtils.isEmpty(bReportPOList)){
                    BigDecimal bigDecimal = bReportPOList.get(0).getQianyuejine();
                    TProjectReportDTO dtoA = new TProjectReportDTO();
                    BeanUtils.copyProperties(reportPO, dtoA);
                    String reportId = IdUtil.simpleUUID();
                    dtoA.setReportId(reportId);
                    dtoA.setNum(bigDecimal.subtract(reportPO.getNum()));
                    dtoA.setReportType(1);
                    dtoA.setDescribes(ProjectReportEnum.A.getCode());
                    dtoA.setSource("LTC");
                    dtoA.setReportDate(LocalDate.now());
                    dtoA.setCreatedBy(SYSTEM_USER);
                    dtoA.setModifiedBy(SYSTEM_USER);
                    log.info("保存项目回款统计-未回款：{}",JSON.toJSON(dtoA));
                    tProjectReportMapper.insertProjectReport(dtoA);
                }

                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(1);
                dto.setDescribes(ProjectReportEnum.B.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("保存项目回款统计-已回款：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }
    }

    /**
     * 插入交付成本统计报表数据
     * @throws Exception
     */
    public void projectDeliveryCost(List<AddProjectReportPO> cReportPOList) {
        if (CollectionUtils.isEmpty(cReportPOList)){
            return;
        }
        for (AddProjectReportPO reportPO : cReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                List<TRbhetong0DTO> bReportPOList = tRbhetong0Mapper.rbHeTong(reportPO.getProjectCode()); //查询合同
                if (!CollectionUtils.isEmpty(bReportPOList)) {
                    // 交付成本上限金额 = 合同未税金额 *【（100-实际利润率）/100】；
                    BigDecimal bigDecimal = bReportPOList.get(0).getQianyuejineweishui();
                    BigDecimal sub_shijilirunlv = new BigDecimal(100).subtract(bReportPOList.get(0).getShijilirunlv());
                    BigDecimal sub = sub_shijilirunlv.divide(new BigDecimal(100));
                    BigDecimal num = bigDecimal.multiply(sub).setScale(2, RoundingMode.HALF_UP);
                    TProjectReportDTO dtoA = new TProjectReportDTO();
                    BeanUtils.copyProperties(reportPO, dtoA);
                    String reportId = IdUtil.simpleUUID();
                    dtoA.setReportId(reportId);
                    dtoA.setNum(num);
                    dtoA.setReportType(2);
                    dtoA.setDescribes(ProjectReportEnum.C.getCode());
                    dtoA.setSource("LTC");
                    dtoA.setReportDate(LocalDate.now());
                    dtoA.setCreatedBy(SYSTEM_USER);
                    dtoA.setModifiedBy(SYSTEM_USER);
                    log.info("插入交付成本统计报表数据-项目交付成本上限：{}",JSON.toJSON(dtoA));
                    tProjectReportMapper.insertProjectReport(dtoA);
                }
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(2); // 2交付成本
                dto.setDescribes(ProjectReportEnum.D.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("插入交付成本统计报表数据-已发生成本：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }
    }

    /**
     * 插入回款金额概况报表数据
     * @throws Exception
     */
    public void projectReceivableMoney(List<AddProjectReportPO> aReportPOList, List<AddProjectReportPO> bReportPOList, List<AddProjectReportPO> dReportPOList) {
        if (CollectionUtils.isEmpty(aReportPOList)){
            return;
        }

        for (AddProjectReportPO reportPO : bReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())) {
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(3); // 2交付成本
                dto.setDescribes(ProjectReportEnum.E.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("回款金额概况-项目金额：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }

        for (AddProjectReportPO reportPO : dReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(3);
                dto.setDescribes(ProjectReportEnum.F.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("回款金额概况-开票金额：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }

        for (AddProjectReportPO reportPO : aReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(3);
                dto.setDescribes(ProjectReportEnum.G.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("回款金额概况-实际回款：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }
    }

    /**
     * 支出金额报表数据
     * @throws Exception
     */
    public void projectSpendingAmount(List<AddProjectReportPO> eReportPOList, List<AddProjectReportPO> cReportPOList) {
        for (AddProjectReportPO reportPO : eReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(4);
                dto.setDescribes(ProjectReportEnum.H.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("支出金额概况-.收票金额：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }
        for (AddProjectReportPO reportPO : cReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(4);
                dto.setDescribes(ProjectReportEnum.I.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("支出金额概况-.实际已付款：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }
    }

    /**
     * 支出费用明细
     * @throws Exception
     */
    public void projectSpendingDetail(List<AddProjectReportPO> cReportPOList, List<AddProjectReportPO> fgReportPOList, List<AddProjectReportPO> oReportPOList, List<AddProjectReportPO> pqReportPOList){
        for (AddProjectReportPO reportPO : cReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(5);
                dto.setDescribes(ProjectReportEnum.J.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("支出费用明细-分包采购费用：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }

        for (AddProjectReportPO reportPO : fgReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(5);
                dto.setDescribes(ProjectReportEnum.K.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("支出费用明细-投标费用：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }

        for (AddProjectReportPO reportPO : oReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(5);
                dto.setDescribes(ProjectReportEnum.L.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("支出费用明细-佣金：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }

        for (AddProjectReportPO reportPO : pqReportPOList) {
            if (StringUtils.isNotBlank(reportPO.getProjectCode())){
                TProjectReportDTO dto = new TProjectReportDTO();
                BeanUtils.copyProperties(reportPO, dto);
                String reportId = IdUtil.simpleUUID();
                dto.setReportId(reportId);
                dto.setReportType(5);
                dto.setDescribes(ProjectReportEnum.M.getCode());
                dto.setSource("LTC");
                dto.setReportDate(LocalDate.now());
                dto.setCreatedBy(SYSTEM_USER);
                dto.setModifiedBy(SYSTEM_USER);
                log.info("支出费用明细-其他：{}",JSON.toJSON(dto));
                tProjectReportMapper.insertProjectReport(dto);
            }
        }
    }

}
